<template>
  <!-- 关联选择器 如城市选择器 -->
  <!-- 关联选择器 如城市选择器 -->
  <mxp-picker ref="mxpPickerRef" v-bind="options"></mxp-picker>
</template>

<script lang="ts" setup>
  import type { $ToolbarProps } from '../mxp-toolbar/mxp-toolbar.vue';
  import { ref } from 'vue';
  import MxpPicker, { type $PickerChangeResult, type $PickerConfirmResult } from '@/mxp-ui/mxp-picker/mxp-picker.vue';
  import type { $AllColorStr, $SizeUnitStr } from '../mxp-tool/types/interface';
  import { removeObjectEmpty } from '../mxp-tool/utils/obj';

  export type $ListItem = Record<number | string, unknown>;
  export type $PickerRelevanceChangeResult = $PickerChangeResult;
  export type $PickerRelevanceConfirmResult = $PickerConfirmResult;
  export type $PickerProps = {
    /** 数组 需要展示的数据 可以是一维数组和二维数组 */
    list?: $ListItem[];
    /** 当为对象数组时,需要展示的 key,不传则取 valueKey,如果 lvalueKey 也没传则为 'label' */
    labelKey?: number | string; // eslint-disable-line vue/no-unused-properties
    /** 当为对象数组时.需要返回的值的 key，不传则取 labelKey,如果 labelKey 也没传则为 'value' */
    valueKey?: number | string; // eslint-disable-line vue/no-unused-properties
    /** 当为关联选择器时，下级list 的 key */
    childKey?: number | string; // eslint-disable-line vue/no-unused-properties
    /** 层级，最多支持五级 */
    level?: 1 | 2 | 3 | 4 | 5; // eslint-disable-line vue/no-unused-properties
    /** 背景颜色 */
    background?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 文本的颜色 */
    color?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 选中的文本颜色 */
    activeColor?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 默认文字的大小 */
    fontSize?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 选中的默认文字的大小 */
    activeFontSize?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 偏移量 （如自定义底部的tabbar就需要一个偏移量） */
    offsetBottom?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 默认选中的数据 */
    defaultValue?: any; // eslint-disable-line vue/no-unused-properties
    /** 是否留出安全区域 */
    safeSrea?: boolean; // eslint-disable-line vue/no-unused-properties
    /** zIndex */
    zIndex?: number; // eslint-disable-line vue/no-unused-properties
    /** 标题 */
    title?: string; // eslint-disable-line vue/no-unused-properties
    /** 是否显示顶部工具栏 */
    showToolbar?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 顶部工具栏配置项 */
    toolbarOptions?: $ToolbarProps; // eslint-disable-line vue/no-unused-properties
    /** 每列显示多少排 */
    showItemCount?: number; // eslint-disable-line vue/no-unused-properties
    /** 单个选项的高度 */
    itemHeight?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 遮罩的背景色 */
    maskBackground?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 是否可以点击遮罩关闭 */
    maskClose?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 加载状态图标的颜色 */
    loadingIconColor?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 点击确认按钮，是否自动关闭  */
    autoClose?: boolean; // eslint-disable-line vue/no-unused-properties
  };

  export type $CallBack = {
    confirm?: (data: $PickerRelevanceConfirmResult) => void;
    change?: (data: $PickerRelevanceChangeResult) => void;
  };
  export type $Options = $CallBack & $PickerProps;

  type $NewOptions = $CallBack & Omit<Required<$PickerProps>, 'list'> & { list: Record<number | string, unknown>[][] };

  defineOptions({
    name: 'mxp-picker-relevance',
  });

  const props = withDefaults(defineProps<$PickerProps>(), {
    background: undefined as $AllColorStr | undefined,
    offsetBottom: '0px',
    showSecond: false,
    level: 3 as 1 | 2 | 3 | 4 | 5 | undefined,
    safeSrea: true,
    zIndex: 888,
    title: '请选择',
    toolbarOptions: () => ({}),
    list: () => [],
    labelKey: undefined as number | string | undefined,
    valueKey: undefined as number | string | undefined,
    defaultValue: [],
    showToolbar: true,
    color: undefined as $AllColorStr | undefined,
    activeColor: undefined as $AllColorStr | undefined,
    fontSize: '14px',
    activeFontSize: '16px',
    showItemCount: 7,
    itemHeight: '44px',
    maskBackground: undefined as $AllColorStr | undefined,
    maskClose: undefined as boolean | undefined,
    loadingIconColor: undefined as $AllColorStr | undefined,
    childKey: 'child',
    autoClose: true,
  });

  /** 原始数据 */
  let originalList = props.list;

  const options = ref<$NewOptions>(JSON.parse(JSON.stringify(props)));
  const mxpPickerRef = ref<InstanceType<typeof MxpPicker> | null>(null);
  /** 显示 */
  function show(param: $Options = {}) {
    init(param);
    mxpPickerRef.value?.show({
      ...options.value,
      confirm(data: $PickerConfirmResult) {
        typeof options.value.confirm === 'function' && options.value.confirm(data);
      },
      change(data: $PickerChangeResult) {
        const { selected, levelIndex } = data;
        const newSelected = [...selected.valueList].splice(0, levelIndex + 1);
        options.value.defaultValue = newSelected;
        const list: $ListItem[][] = getList(originalList, options.value, newSelected, 0, [options.value.list[0]!]);
        options.value.list = list;
        mxpPickerRef.value?.undateList(list, newSelected);
        typeof options.value.change === 'function' && options.value.change(data);
      },
    });
  }

  /**
   * 隐藏
   */
  function hide() {
    mxpPickerRef.value?.hide();
  }

  /** 初始化 */
  function init(param: $Options = {}) {
    const op: $Options = { ...props, ...removeObjectEmpty(param) };
    op.level = op?.level || 1;
    const _labelKey = op.labelKey || op.valueKey;
    const _valueKey = op.valueKey || op.labelKey;
    // 防止为 0 时被默认为 'label' 或者 'value'
    op.labelKey = _labelKey === 0 ? 0 : _labelKey || 'label';
    op.valueKey = _valueKey === 0 ? 0 : _valueKey || 'value';
    op.childKey = op.childKey === 0 ? 0 : op.childKey || 'value';
    originalList = op.list!;
    op.defaultValue = Array.isArray(op.defaultValue) ? op.defaultValue : [op.defaultValue];
    const list: $ListItem[][] = getList(originalList!, op, op.defaultValue, 0, [getItem(originalList!, op)]);
    options.value = { ...(op as $CallBack & Required<$PickerProps>), list };
  }

  /**
   * 递归 得到 list
   */
  function getList(list: $ListItem[], op: $NewOptions | $Options, defaultValue: unknown[], index: number, newList: $ListItem[][]): $ListItem[][] {
    const curVal: unknown = defaultValue[index];
    let curIndex = list.findIndex((item) => item[op.valueKey!] === curVal);
    curIndex = curIndex < 0 ? 0 : curIndex;
    const obj = list![curIndex];
    if (obj && Array.isArray(obj[op.childKey!])) {
      const child = (Array.isArray(obj[op.childKey!]!) ? obj[op.childKey!]! : []) as $ListItem[];
      newList.push(getItem(child, op));
      getList(child, op, defaultValue, index + 1, newList);
    }
    return newList;
  }

  /** 得到 item */
  function getItem(list: $ListItem[], op: $NewOptions | $Options): $ListItem[] {
    return list.map((item) => {
      return {
        [op.labelKey!]: item[op.labelKey!] || '',
        [op.valueKey!]: item[op.valueKey!] || '',
      } as Record<number | string, unknown>;
    });
  }

  /** 设置加载状态 */
  function setLoadState(state: boolean) {
    mxpPickerRef.value?.setLoadState(Boolean(state));
  }

  defineExpose({
    /** 显示 */
    show,
    /** 隐藏 */
    hide,
    /** 提交 */
    confirm,
    /** 设置加载状态 */
    setLoadState,
  });
</script>

<style lang="scss" scoped>
  .loading-box {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    z-index: 9999;
    display: flex;
    flex-flow: column nowrap;
    align-items: center;
    justify-content: center;
    height: 100%;
  }

  .picker-view-box-vessel {
    display: flex;
    flex-flow: column nowrap;
    align-items: center;
    justify-content: space-between;
    width: 750rpx;

    .picker-view {
      width: 750rpx;
      height: 200px;

      .picker-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        height: 40px;
        font-size: 13px;
        line-height: 40px;
        text-align: center;
      }
    }
  }
</style>
